package dao

import (
	"context"
	"errors"
	"fmt"
	"github.com/qiniu/qmgo"
	"github.com/sirupsen/logrus"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
	"monoblog/config"
	"monoblog/domain/model"
	"sync"
)

var (
	userInterestRepo *UserInterestRepository // 单例实例存储变量
	once5            sync.Once               // 确保初始化只执行一次的同步工具
)

// 初始化 QMGO 集合（单例模式）
func NewUserInterestRepository() *UserInterestRepository {
	once5.Do(func() { // 并发安全的初始化逻辑，只会执行一次
		userInterestRepo = &UserInterestRepository{
			collection: config.GetDataBase().Collection(model.UserInterestCollectionName), //指定集合名称
			ctx:        context.Background(),
		}
	})
	return userInterestRepo // 返回唯一实例
}

type UserInterestRepository struct {
	collection *qmgo.Collection // QMGO 集合对象（替代原生 mongo.Collection）
	ctx        context.Context  // 上下文（用于数据库操作超时控制）
}

func (impl UserInterestRepository) Add(userInterest *model.UserInterest) error {
	r, err := impl.collection.InsertOne(impl.ctx, userInterest)
	if oid, ok := r.InsertedID.(primitive.ObjectID); ok {
		userInterest.UserId = oid.Hex()
	}
	return err
}

func (impl UserInterestRepository) DeleteByUserId(userId string) error {
	filter := qmgo.M{"userId": userId}

	// 执行删除操作
	err := impl.collection.Remove(impl.ctx, filter)
	if errors.Is(err, mongo.ErrNoDocuments) {
		logrus.Warnf("record not found. dont delete. userId: %v", userId)
		return nil
	}
	return err
}

func (impl UserInterestRepository) FindByUserId(userId string) (*model.UserInterest, error) {
	var userInterest model.UserInterest

	err := impl.collection.Find(impl.ctx, qmgo.M{"userId": userId}).One(&userInterest)

	if errors.Is(err, mongo.ErrNoDocuments) {
		logrus.Warnf("record not found. userId: %v", userId)
		return nil, errors.New("找不到数据, userId: " + userId)
	}
	return &userInterest, err
}

func (impl UserInterestRepository) AppendFollowId(followId string, userId string) error {
	return impl.appendElement("followIds", followId, userId)
}

func (impl UserInterestRepository) RemoveFollowId(followId string, userId string) error {
	return impl.removeElement("followIds", followId, userId)
}

func (impl UserInterestRepository) ExistsFollowId(followId string, userId string) (bool, error) {
	return impl.existsElement("followIds", followId, userId)
}

func (impl UserInterestRepository) AppendFansId(fansId string, userId string) error {
	return impl.appendElement("fansIds", fansId, userId)
}

func (impl UserInterestRepository) RemoveFansId(fansId string, userId string) error {
	return impl.removeElement("fansIds", fansId, userId)
}
func (impl UserInterestRepository) ExistsFansId(fansId string, userId string) (bool, error) {
	return impl.existsElement("fansIds", fansId, userId)
}

func (impl UserInterestRepository) AppendBlack(blackId string, userId string) error {
	return impl.appendElement("blacklistIds", blackId, userId)
}

func (impl UserInterestRepository) RemoveBlackId(blackId string, userId string) error {
	return impl.removeElement("blacklistIds", blackId, userId)
}

func (impl UserInterestRepository) ExistsBlackId(blackId string, userId string) (bool, error) {
	return impl.existsElement("blacklistIds", blackId, userId)
}

// appendElement 追加用户兴趣元素
func (impl UserInterestRepository) appendElement(field string, element string, userId string) error {
	filter := qmgo.M{"userId": userId}

	update := qmgo.M{"$addToSet": qmgo.M{field: element}}

	err := impl.collection.UpdateOne(impl.ctx, filter, update)
	if err != nil {
		logrus.Errorf("append %v failed. userId: %v . err: %v", field, userId, err.Error())
		return errors.New(fmt.Sprintf("append %v failed.", field))

	}
	return nil
}

func (impl UserInterestRepository) removeElement(field string, element string, userId string) error {
	filter := qmgo.M{"userId": userId}

	update := qmgo.M{"$pull": qmgo.M{field: element}}

	err := impl.collection.UpdateOne(impl.ctx, filter, update)
	if err != nil {
		logrus.Errorf("remove %v failed. userId: %v . err: %v", field, userId, err.Error())
		return errors.New(fmt.Sprintf("remove %v failed.", field))

	}
	return nil
}

// existsElement 检查用户兴趣元素是否存在
func (impl UserInterestRepository) existsElement(field, element string, userId string) (bool, error) {
	// 构建查询条件：匹配用户ID，且field数组包含目标element
	filter := qmgo.M{"userId": userId, field: element}

	// 执行查询并统计匹配文档数量
	count, err := impl.collection.Find(impl.ctx, filter).Count()
	if err != nil {
		logrus.Errorf("exists %v failed. userId: %v . err: %v", field, userId, err.Error())
		return false, errors.New(fmt.Sprintf("exists %v failed.", field))
	}
	return count > 0, nil
}
